<template>
    <div 
        class="text-dom-container"
        @mouseenter="enterFlag = true"
        @mouseleave="enterFlag = false"
        @keyup="mouseDown"
        >
        <!-- 允许编辑 -->
        <div class="text-dom-area-box">
            <div 
                class="text-dom-area"
                :class="[!textLength ? '' : 'text-dom-placeholder']"
                :style="{ padding: clearable ? '4px 30px 4px 8px' : '4px 8px'}"
                contenteditable 
                ref="textArea"
                @input="input"
                @focus="focusFlag = true"
                @blur="focusFlag = false"
                @keydown="backspace"
            >
                {{ text }}
            </div>

            <!-- icon -->
            <svg
                v-show="clearable && (enterFlag || focusFlag)" 
                viewBox="0 0 100 100" 
                xmlns="http://www.w3.org/2000/svg" 
                style="width: 14px; height: 14px"
                @click="clearText"
            >
                <!-- 第一条对角线 -->
                <line x1="35" y1="35" x2="65" y2="65" stroke="#818181" stroke-width="4" />
                <!-- 第二条对角线 -->
                <line x1="65" y1="35" x2="35" y2="65" stroke="#818181" stroke-width="4" />
                <!-- 围绕X的圆形 -->
                <circle cx="50" cy="50" r="45" stroke="#818181" stroke-width="4" fill="none" />
            </svg>
        </div>

        <!-- 出现@符号时，自动创建一个span元素 -->
        <TextSelect v-if="showSelect" :area="textArea">
            <slot></slot>
        </TextSelect>
    </div>
</template>
  
<script setup>
import { ref, onMounted, nextTick, computed, watch, onBeforeUnmount } from 'vue'
import TextSelect from './TextSelect.vue'

const emit = defineEmits(['clear', 'input'])
const props = defineProps({
    // 回显的文本
    defaultText: String,
    // 是否显示删除按钮
    clearable: Boolean,
    // 唤起弹窗的符号
    symbols: {
        type: String,
        default: '@'
    },
    // 输入框的占位符
    placeholder: {
        type: String,
        default: '请输入'
    }
})
const text = ref('')
const textArea = ref(null)
const showSelect = ref(false)
// 鼠标移入标志
const enterFlag = ref(false)
// 聚焦标志
const focusFlag = ref(false)
// 当前选中的文本（主要服务@唤起的列表时，键盘上下按钮切换功能）

function getTextBeforeCursor() {
    const selection = window.getSelection();
    if (!selection.rangeCount) return '';

    const range = selection.getRangeAt(0);
    const preCaretRange = range.cloneRange();
    preCaretRange.selectNodeContents(textArea.value);
    preCaretRange.setEnd(range.endContainer, range.endOffset);
    
    // Create a temporary div to hold the content
    const tempDiv = document.createElement('div');
    tempDiv.appendChild(preCaretRange.cloneContents());
    // Get the HTML content
    const htmlContent = tempDiv.innerHTML;
    // result.textContent = 'Text before cursor:\n' + htmlContent;
    return htmlContent
}

// 删除当前光标前面@符号
const deleteAtSymbol = () => {
    // 获取选择范围
    const range_temp = window.getSelection().getRangeAt(0);
    console.log(range_temp)
    // 设置范围的起始点为当前光标位置的前一个字符
    range_temp.setStart(range_temp.startContainer, Math.max(0, range_temp.startOffset - 1));
    // 设置范围的结束点为当前光标位置
    range_temp.setEnd(range_temp.startContainer, range_temp.startOffset + 1);
    // 删除选中的文本
    range_temp.deleteContents();
}

// textArea的innerHTML变化
const textAreaChange = () => {
    emit('input', textArea.value.innerHTML)
}

// 默认回显给元素添加contenteditable="false"属性
function addContentEditableFalse(html) {
  // 使用正则表达式匹配所有的<span>标签
  const spanRegex = /<span([^>]*)>/g;
  // 替换函数，用于在匹配到的<span>标签中添加contenteditable="false"属性
  const replacer = (match, p1) => {
    // 检查是否已经存在contenteditable属性
    if (p1.includes('contenteditable')) {
      // 如果存在，替换现有的contenteditable属性
      return `<span${p1.replace(/contenteditable=["'].*?["']/, 'contenteditable="false"')}>`;
    } else {
      // 如果不存在，添加contenteditable="false"属性
      return `<span${p1}${p1 ? ' ' : ''} contenteditable="false">`;
    }
  };
  // 使用replace方法替换所有的<span>标签
  return html.replace(spanRegex, replacer);
}

// 更新元素
const updateElement = (element) => {
    element.innerHTML = `&nbsp${element.innerHTML}&nbsp`
    textArea.value.focus();
    nextTick(() => {
        element.contentEditable = false;
        const selection = window.getSelection();
        const range = selection.getRangeAt(0);
        range.deleteContents();
        range.insertNode(element);
        range.setStartAfter(element);
        range.setEndAfter(element);
        selection.removeAllRanges();
        selection.addRange(range);
        // selection.collapse(element.nextSibling, 0);
        showSelect.value = false
        textAreaChange()
    })
}


// 插入@符号创建的元素
const setText = (element) => {
    deleteAtSymbol()
    updateElement(element)
}

const input = (e) => {
    const selection = window.getSelection();
    const range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
    const cursorPosition = range ? range.startOffset : 0;
    const previousChar = range ? range.startContainer.textContent[cursorPosition - 1] : '';
    const isAtSymbol = previousChar === props.symbols;
    
    // 防止空内容时自动插入br
    if (textArea.value.innerHTML === '<br>') {
        textArea.value.innerHTML = '';
    }
    
    if (isAtSymbol) {
        showSelect.value = true;
    } else {
        showSelect.value = false;
    }
    textAreaChange()
}

// 清空文本
const clearText = () => {
    text.value = ''
    textArea.value.innerHTML = ''
    showSelect.value = false
    emit('clear')
}

// 上下切换
const mouseDown = (e) => {
    if (!showSelect.value) return
    // 如果键盘按下的是下方向
    if (e.keyCode === 40) {
        console.log(e.target, '下')
    } else if (e.keyCode === 38) {
        console.log(e.target, '上')
    }
}

let observer = null
const textLength = ref(0)
// 检测textArea元素变化 所有内部，只要变了就触发
const textAreaChangeHandler = () => {
    observer = new MutationObserver((mutationsList) => {
        for (let mutation of mutationsList) {
            textLength.value = textArea.value.innerText.length
        }
    })
    observer.observe(textArea.value, { childList: true, subtree: true, characterData: true })
}

function getPreviousCharacter(inputElement) {
    var caretPos = inputElement.selectionStart;
    var text = inputElement.value;
    console.log(inputElement, inputElement.innerHTML)
    // 检查光标位置是否大于0，以避免在文本开头时出现错误
    if (caretPos > 0) {
        // 返回光标前一个字符
        return text.charAt(caretPos - 1);
    } else {
        // 如果光标在文本开头，则没有前一个字符
        return null;
    }
}

function getLastTag(str) {
    // 创建一个临时的div来解析HTML
    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = str;
    
    // 获取最后一个子节点
    const lastChild = tempDiv.lastChild;
    // console.log(tempDiv.lastChild)
    // 如果最后一个节点不是元素节点，返回false
    if (!lastChild || lastChild.nodeType !== Node.ELEMENT_NODE) {
        return false;
    }
    
    // 检查字符串是否以这个标签结尾
    const lastTag = lastChild.outerHTML;
    if (str.endsWith(lastTag)) {
        return lastTag;
    }
    
    return false;
}

const backspace = (event) => {
    // console.log(event, event.key)
    if (event.key === 'Backspace') {
        event.preventDefault();
        const ele = getTextBeforeCursor()
        console.log(getLastTag(ele))
        // return
        // const selection = window.getSelection();
        // if (selection.rangeCount > 0) {
        //     const range = selection.getRangeAt(0);
        //     const startContainer = range.startContainer;
        //     // console.log(getPreviousCharacter(textArea.value))
        //     if (startContainer.nodeType === Node.ELEMENT_NODE && startContainer.contentEditable === 'false') {
        //         console.log(startContainer, startContainer.nodeType, Node.ELEMENT_NODE, startContainer.contentEditable, range)
        //         event.preventDefault();
        //         startContainer.remove();
        //     } else {
        //         console.log('不是元素节点',startContainer)
        //     }
        // }
    }
}

watch(() => props.placeholder, (newVal) => {
    nextTick(() => {
        textArea.value.style.setProperty('--placeholder', `"${newVal}"`)
    })
}, { deep: true, immediate: true })

onMounted(() => {
    textAreaChangeHandler()
    if (props.defaultText) {
        // updateElement(props.defaultText)
        if (props.defaultText) {
            textArea.value.innerHTML = addContentEditableFalse(props.defaultText)
            return
        }
    }
})

onBeforeUnmount(() => {
    observer && observer.disconnect()
})

defineExpose({
    setText
})
</script>

<style scoped lang="scss">
.text-dom-container {
    width: 100%;
    position: relative;
    .text-dom-area-box {
        position: relative;
        svg {
            cursor: pointer;
            position: absolute;
            right: 10px;
            top: 50%;
            transform: translateY(-50%);
            z-index: 1;
            
            &:hover {
            line {
                    stroke: #000;
                    transition: all .2s;
            }
            circle {
                    stroke: #000;
                    transition: all .2s;
            }
            }
        }
        .text-placeholder {
            position: absolute;
            left: 0;
            top: 0;
            z-index: 0;
            line-height: 32px;
            font-size: 14px;
            color: #cac2d6;
        }
    }
    .text-dom-area {
        --placeholder: '请输入';
        position: relative;
        z-index: 1;
        width: 100%;
        overflow-y: auto;
        line-height: 32px;
        border: 1px solid #ccc;
        border-radius: 4px;
        box-sizing: border-box;
        font-size: 14px;
        &:focus {
            outline: none;
            border-color: #409eff;
            transition: border-color .2s cubic-bezier(.645,.045,.355,1);
        }
        // &::after {
        //     content: var(--placeholder);
        //     position: absolute;
        //     pointer-events: none;
        //     cursor: pointer;
        //     box-sizing: border-box;
        //     width: 100%;
        //     height: 100%;
        //     padding: 4px 8px;
        //     color: #cac2d6;
        //     left: 0;
        //     top: 0;
        //     z-index: 0;
        // }
    }
    .text-dom-placeholder {
        // &::after {
        //     content: '';
        // }
    }
}
</style>

<style lang="scss">
@import './textDom.scss';
</style>